//
// Created by martin on 2/8/22.
//

#ifndef MUDUO_TIMERQUEUE_H
#define MUDUO_TIMERQUEUE_H

#include "muduo/base/Timestamp.h"
#include "muduo/net/TimerId.h"
#include "muduo/net/Callbacks.h"
#include "muduo/net/Channel.h"

#include <set>
#include <vector>
#include <utility>

namespace muduo
{
namespace net
{
class EventLoop;

/**
 * 定时器队列.
 * 不能保证回调能及时调用.
 *
 * 只能在所在loop线程中运行, 因此线程安全是非必须的
 */
class TimerQueue : noncopyable
{
public:
    explicit TimerQueue(EventLoop* loop);
    ~TimerQueue();
    /*
     * 添加一个定时器.
     * 运行到指定时间， 调度相应的回调函数.
     * 如果interval参数 > 0.0, 就周期重复运行.
     * 必须线程安全: 可能会由其他线程调用
     */
    TimerId addTimer(TimerCallback cb, Timestamp when, double interval);
    /* 取消指定TimerId的定时器 */
    void cancel(TimerId);

private:
    /**
     * FIXME: use unique_ptr<Timer> instead of raw pointers.
     * This requires heterogeneous comparison lookup (N3456) from C++14
     * so that we can find an T* in a set<unique_ptr<T>>.
     */
    typedef std::pair<Timestamp, Timer*> Entry;
    typedef std::set<Entry> TimerList;
    typedef std::pair<Timer*, int64_t> ActiveTimer;
    typedef std::set<ActiveTimer> ActiveTimerSet;

    void addTimerInLoop(Timer* timer);
    void cancelInLoop(TimerId timerId);
    // called when timerfd alarms
    void handleRead();
    // move out all expired timers
    std::vector<Entry> getExpired(Timestamp now);
    void reset(const std::vector<Entry>& expired, Timestamp now);

    bool insert(Timer* timer);

    EventLoop* loop_;
    const int timerfd_;
    Channel timerfdChannel_; // watch readable event of timerfd
    // Timer list sorted by expiration
    /* 用户添加的所有Timer对象集合
     * 需要为set元素比较实现operator< */
    TimerList timers_;

    // for cancel()
    ActiveTimerSet activeTimers_; // 激活的定时器集合
    bool callingExpiredTimers_;   /* atomic */
    ActiveTimerSet cancelingTimers_;
};

} // namespace net
} // namespace muduo

#endif //MUDUO_TIMERQUEUE_H
